

package jframe.utils;

import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import sun.net.TelnetInputStream;
import sun.net.TelnetOutputStream;
import sun.net.ftp.FtpClient;

/**
 * @描述:<p>FTP工具类</p>
 *
 * @作者: 叶平平(yepp)
 *
 * @时间: 2011-12-27 下午09:14:45
 */
public class FtpUtil {
	
	private String ip = "";     
    
    private String username = "";     
    
    private String password = "";     
    
    private int port = -1;     
    
    private String path = "";     
    
    FtpClient ftpClient = null;     
    
    OutputStream os = null;     
    
    FileInputStream is = null;     
    
    /**
     * 构造方法
     */
    public FtpUtil(String serverIP, String username, String password) {     
        this.ip = serverIP;     
        this.username = username;     
        this.password = password;     
    }     
         
    /**
     * 构造方法
     */
    public FtpUtil(String serverIP, int port, String username, String password) {     
        this.ip = serverIP;     
        this.username = username;     
        this.password = password;     
        this.port = port;     
    }     
    /**
     * @描述:<p> 连接ftp服务器 </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:32:16
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @return
     */
    public boolean connectServer(){     
        ftpClient = new FtpClient();     
        try {     
            if(this.port != -1){     
                    ftpClient.openServer(this.ip,this.port);     
            }else{     
                ftpClient.openServer(this.ip);     
            }     
            ftpClient.login(this.username, this.password);     
            if (this.path.length() != 0){     
                ftpClient.cd(this.path);// path是ftp服务下主目录的子目录                
            }     
            ftpClient.binary();// 用2进制上传、下载     
            System.out.println("已登录到\"" + ftpClient.pwd() + "\"目录");     
            return true;     
        }catch (IOException e){     
            e.printStackTrace();     
            return false;     
        }     
    }     
   
    /**
     * @描述:<p> 断开与ftp服务器连接 </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:32:03
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @return
     */
    public boolean closeServer(){     
        try{     
            if (is != null) {     
                is.close();     
            }     
            if (os != null) {     
                os.close();     
            }     
            if (ftpClient != null) {     
                ftpClient.closeServer();     
            }     
            System.out.println("已从FTP服务器断开");     
            return true;
        }catch(IOException e){
            e.printStackTrace();
            return false;
        }
    }  
     /**
     * @描述:<p> 检查文件夹在当前目录下是否存在  </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:31:40
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param dir
     * @return
     */
    private boolean isDirExist(String dir){     
         String pwd = "";     
         try {     
             pwd = ftpClient.pwd();     
             ftpClient.cd(dir);     
             ftpClient.cd(pwd);     
         }catch(Exception e){     
             return false;     
         }     
         return true;      
     }     
            
     /**
     * @描述:<p> 在当前目录下创建文件夹  </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:31:28
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param dir
     * @return
     */
    private boolean createDir(String dir){     
         try{     
            ftpClient.ascii();     
            StringTokenizer s = new StringTokenizer(dir, "/"); //sign     
            s.countTokens();     
            String pathName = ftpClient.pwd();     
            while(s.hasMoreElements()){     
                pathName = pathName + "/" + (String) s.nextElement();     
                try {     
                    ftpClient.sendServer("MKD " + pathName + "\r\n");     
                } catch (Exception e) {     
                    e = null;     
                    return false;     
                }     
                ftpClient.readServerResponse();     
            }     
            ftpClient.binary();     
            return true;     
        }catch (IOException e1){     
            e1.printStackTrace();     
            return false;     
        }     
     }     
            
    /**
     * @描述:<p> ftp上传
     * 如果服务器段已存在名为filename的文件夹，该文件夹中与要上传的文件夹中同名的文件将被替换
     *  </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:30:55
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param filename	要上传的文件（或文件夹）名   
     * @return
     */
    public boolean upload(String filename){     
        String newname = "";     
        if(filename.indexOf("/") > -1){     
            newname = filename.substring(filename.lastIndexOf("/") + 1);     
        }else{     
            newname = filename;     
        }     
        return upload(filename, newname);     
    }     
            
     /**
     * @描述:<p>ftp上传 
     * 如果服务器段已存在名为newName的文件夹，该文件夹中与要上传的文件夹中同名的文件将被替换
     *  </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:30:00
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param fileName	要上传的文件（或文件夹）名 
     * @param newName	服务器段要生成的文件（或文件夹）名   
     * @return
     */
    public boolean upload(String fileName, String newName){     
         try{     
             String savefilename = new String(fileName.getBytes("ISO-8859-1"), "GBK");      
             File file_in = new File(savefilename);//打开本地待长传的文件     
             if(!file_in.exists()){     
                 throw new Exception("此文件或文件夹[" + file_in.getName() + "]有误或不存在!");     
             }     
             if(file_in.isDirectory()){     
                 upload(file_in.getPath(),newName,ftpClient.pwd());     
             }else{     
                 uploadFile(file_in.getPath(),newName);     
             }     
                  
             if(is != null){     
                 is.close();     
             }     
             if(os != null){     
                 os.close();     
             }     
             return true;     
         }catch(Exception e){      
                e.printStackTrace();      
                System.err.println("Exception e in Ftp upload(): " + e.toString());      
                return false;     
         }finally{     
             try{     
                 if(is != null){     
                     is.close();     
                 }     
                 if(os != null){      
                     os.close();      
                 }     
             }catch(IOException e){     
                 e.printStackTrace();     
            }      
         }     
     }     
            
     /**
     * @描述:<p>真正用于上传的方法   </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:29:18
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param fileName	要上传的文件名
     * @param newName	上传后的新文件名   
     * @param path		路径
     * @throws Exception
     */
    private void upload(String fileName, String newName,String path) throws Exception{     
         String savefilename = new String(fileName.getBytes("ISO-8859-1"), "GBK");      
         File file_in = new File(savefilename);//打开本地待长传的文件     
         if(!file_in.exists()){     
             throw new Exception("此文件或文件夹[" + file_in.getName() + "]有误或不存在!");     
         }     
         if(file_in.isDirectory()){     
             if(!isDirExist(newName)){     
                 createDir(newName);     
             }     
             ftpClient.cd(newName);     
             File sourceFile[] = file_in.listFiles();     
             for(int i = 0; i < sourceFile.length; i++){     
                 if(!sourceFile[i].exists()){     
                     continue;     
                 }     
                 if(sourceFile[i].isDirectory()){     
                     this.upload(sourceFile[i].getPath(),sourceFile[i].getName(),path+"/"+newName);     
                 }else{     
                     this.uploadFile(sourceFile[i].getPath(),sourceFile[i].getName());     
                  }     
                }     
         }else{     
             uploadFile(file_in.getPath(),newName);     
         }     
         ftpClient.cd(path);     
     }     
    
    /**
     * @描述:<p>upload 上传文件    </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:28:33
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param filename	要上传的文件名 
     * @param newname	上传后的新文件名   
     * @return		-1 文件不存在 >=0 成功上传，返回文件的大小 
     * @throws Exception
     */
    public long uploadFile(String filename, String newname) throws Exception{     
        long result = 0;     
        TelnetOutputStream os = null;     
        FileInputStream is = null;     
        try {     
            java.io.File file_in = new java.io.File(filename);     
            if(!file_in.exists())     
                return -1;   
            String dirs = newname.substring(0, newname.lastIndexOf("/"));
            ftpClient.cdUp();
            createDir(dirs);
            ftpClient.cdUp();
            os = ftpClient.put(newname);     
            result = file_in.length();     
            is = new FileInputStream(file_in);     
            byte[] bytes = new byte[1024];     
            int c;     
            while((c = is.read(bytes)) != -1){     
                os.write(bytes, 0, c);     
            }     
        }finally{     
            if(is != null){     
                is.close();     
            }     
            if(os != null){     
                os.close();     
            }     
        }     
        return result;     
    }     
     
    /**
     * @描述:<p>从ftp下载文件到本地  </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:28:06
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param filename		服务器上的文件名
     * @param newfilename	本地生成的文件名   
     * @return
     */
    public long downloadFile(String filename, String newfilename){     
        long result = 0;     
        TelnetInputStream is = null;     
        FileOutputStream os = null;     
        try{     
            is = ftpClient.get(filename);
            makeSurePath(newfilename);
            File outfile = new File(newfilename);
            os = new FileOutputStream(outfile);
            byte[] bytes = new byte[1024];     
            int c;     
            while ((c = is.read(bytes)) != -1) {     
                os.write(bytes, 0, c);     
                result = result + c;     
            }     
        }catch (IOException e){     
            e.printStackTrace();     
        }finally{     
            try {     
                if(is != null){     
                        is.close();     
                }     
                if(os != null){     
                    os.close();     
                }     
            } catch (IOException e) {     
                e.printStackTrace();     
            }     
        }     
        return result;     
    }
    
    /**
     * @描述:<p>将文件从一个路径移动到另一个路径
     * 
     *   在FTPClient中，rename既是重命名又是文件移动的操作
     *   
     *   注意：文件路径中需要带完整路径：/aaa/bb/cc/ 最前面和最末端一定要加上“/”
     *   
     *   </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:26:04
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param srcPath	文件源路径
     * @param targetPath	文件目标路径
     * @param fileName		文件名
     */
    public void moveFile(String srcPath,String targetPath,String fileName){
    	try {
            if(!isDirExist(targetPath)){
                createDir(targetPath);
            }
			ftpClient.rename(srcPath+fileName, targetPath+fileName);
			System.out.println("文件移动成功！源路径："+srcPath+fileName+" 目标路径："+targetPath+fileName);
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    /**
     * @描述:<p>确保文件所在的目录是存在的，如果不存在，则创建</p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:27:22
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param fullPath
     */
    public void makeSurePath(String fullPath){
    	File file = new File(fullPath);
    	File folder = new File(file.getParent());
    	if(!folder.exists()){
    		folder.mkdirs();
    	}
    }
      
    /**
     * @描述:<p>取得相对于当前连接目录的某个目录下所有文件列表  </p>
     *
     * @作者:  叶平平(yepp)
     *
     * @时间:  2011-12-30 下午10:27:42
     *
     * @修改历史: <p>修改时间、修改人、修改原因/说明</p>
     *
     * @param path
     * @return
     */
    @SuppressWarnings({ "unchecked", "deprecation" })
	public List getFileList(String path){     
        List list = new ArrayList();     
        DataInputStream dis;     
        try {     
            dis = new DataInputStream(ftpClient.nameList(this.path + path));     
            String filename = "";     
            while((filename = dis.readLine()) != null){     
                list.add(filename);     
            }     
        } catch (IOException e) {     
            e.printStackTrace();     
        }     
        return list;     
    }     
    
         
    
    public static void main(String[] args){     
    	/*    	
        //////
        FTPUtils ftpUtils = new FTPUtils(fileInfo.getFtphost(), fileInfo.getFtpport(), fileInfo.getFtpUserName(), fileInfo.getFtpPw());
		ftpUtils.connectServer();
		try {
			ftpUtils.upload("C:/test_why", "test_why/test");    
			ftpUtils.uploadFile(fileInfo.getLocalZipFilePath(), fileInfo.getFtpSaveZipFilePath());
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			ftpUtils.closeServer();
		}
        */   
        /**   
        FTP远程命令列表   
        USER    PORT    RETR    ALLO    DELE    SITE    XMKD    CDUP    FEAT   
        PASS    PASV    STOR    REST    CWD     STAT    RMD     XCUP    OPTS   
        ACCT    TYPE    APPE    RNFR    XCWD    HELP    XRMD    STOU    AUTH   
        REIN    STRU    SMNT    RNTO    LIST    NOOP    PWD     SIZE    PBSZ   
        QUIT    MODE    SYST    ABOR    NLST    MKD     XPWD    MDTM    PROT   
        在服务器上执行命令,如果用sendServer来执行远程命令(不能执行本地FTP命令)的话，所有FTP命令都要加上\r\n   
        ftpclient.sendServer("XMKD /test/bb\r\n"); //执行服务器上的FTP命令   
        ftpclient.readServerResponse一定要在sendServer后调用   
        nameList("/test")获取指目录下的文件列表   
        XMKD建立目录，当目录存在的情况下再次创建目录时报错   
        XRMD删除目录   
        DELE删除文件   
         */
    }
}
